package com.atguigu.spzx.cart.service.impl;

import com.spzx.cart.domain.CartInfo;
import com.atguigu.spzx.cart.service.CartService;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.domain.ProductSku;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {
    @Resource
    RedisTemplate redisTemplate;
    @Resource
    RemoteProductService remoteProductService;
    //加购
    @Override
    public void add2Cart(Long skuId, Integer skuNum) {
        //1、获取购物车
        BoundHashOperations<String, String, CartInfo> cart = getCart();
        //2、判断购物车中是否已存在skuId的购物项
//        Boolean hasKey = cart.hasKey(skuId.toString());
        CartInfo cartInfo = cart.get(skuId.toString());
        if(cartInfo!=null){
            //skuId已存在，只需要更新他的数量
            cartInfo.setSkuNum(cartInfo.getSkuNum()+skuNum);
            cartInfo.setUpdateTime(new Date());

        }else{//cartInfo == null
            //查询商品详情
            R<ProductSku> skuR = remoteProductService.getSkuBySkuId(skuId);
            if(skuR.getCode()!=200){
                throw new ServiceException("商品不存在!");
            }
            ProductSku productSku = skuR.getData();

            //skuId的购物项不存在，新建购物项存到购物车
            cartInfo = new CartInfo();
            cartInfo.setSkuId(skuId);
            cartInfo.setCreateTime(new Date());
            cartInfo.setUpdateTime(new Date());
            cartInfo.setUserId(SecurityContextHolder.getUserId());
            cartInfo.setSkuNum(skuNum);
            //第一次添加到购物车的商品 默认选中
            cartInfo.setIsChecked(1);


            cartInfo.setCartPrice(productSku.getSalePrice()); //sku的销售价格
            cartInfo.setSkuPrice(productSku.getSalePrice()); //sku最新的价格
            cartInfo.setSkuName(productSku.getSkuName()); //sku标题
            cartInfo.setThumbImg(productSku.getThumbImg()); //sku缩略图
//            cart.put(skuId.toString(),cartInfo);
        }
        //将修改或者初始化后的cartInfo设置到购物车中
        cart.put(skuId.toString() , cartInfo);//相同的属性名，后设置的值会覆盖之前的
    }

    private BoundHashOperations<String, String, CartInfo> getCart() {
    /*
        SecurityContextHolder可以获取用户id的原因：
        1、客户端所有请求提交给了网关
        2、网关通过全局过滤器AuthFilter校验不是白名单的请求
            如果登录状态校验成功，它会将解析到的userId  userName值 添加到请求报文头中  然后放行请求访问目标服务
        3、在目标服务中 通过springmvc的 请求拦截器拦截请求
            获取请求头中的 userId和userName ，缓存到SecurityContextHolder的ThreadLocal中
        4、在具体的业务代码中 就可以使用SecurityContextHolder获取缓存的 userId  userName等数据
     */
//        Long userId = SecurityContextHolder.getUserId();
        //1、获取用户的购物车(在redis中以hash方式保存)
//        redisTemplate.boundHashOps("") 根据key获取redis中的hash结构，java代码中接收的结果类似Map 对应hash结构
        //  userId   skuId  cartInfo
        //泛型1：redis键的类型， 泛型2：hash结构属性的类型  泛型3：hash结构值的类型
        BoundHashOperations<String,String, CartInfo> cart = redisTemplate.boundHashOps("spzx:cart:"+SecurityContextHolder.getUserId());
       //cart就是得到的hash结构
        return cart;
    }

    //查询购物车
    @Override
    public List<CartInfo> selectCartList() {
        //获取当前用户的购物车
        BoundHashOperations<String, String, CartInfo> cart = getCart();
        return cart.values();
    }

    @Override
    public void deleteCart(Long skuId) {
        /*
            BoundHashOperations 泛型2 存储的是skuId，我设置的泛型为String
            但是skuId是Long类型。

            为什么指定为String，因为使用的ry 整合redis时 配置了RedisTemplate的所有key都只能使用字符串
            spzx-common-redis RedisConfig中配置的！
         */
        BoundHashOperations<String, String, CartInfo> cart = getCart();
        cart.delete(skuId.toString());
    }

    @Override
    public void checkCart(Long skuId, Integer status) {
        BoundHashOperations<String, String, CartInfo> cart = getCart();
        CartInfo cartInfo = cart.get(skuId.toString());
        if(cartInfo==null){
            throw new ServiceException("购物项不存在");
        }
        //修改选中状态
        cartInfo.setIsChecked(status);
        //同步到redis中
        cart.put(skuId.toString() , cartInfo);
    }

    @Override
    public void allCheckCart(Integer status) {
        BoundHashOperations<String, String, CartInfo> cart = getCart();
        cart.entries() //map中的k-v绑定为了Entry对象存储
                .forEach((skuIdStr , cartInfo)->{
            cartInfo.setIsChecked(status);
            cart.put(skuIdStr,cartInfo);
        });
    }

    @Override
    public void clearCart() {
        //删除userId对应的hash结构
        redisTemplate.delete("spzx:cart:"+SecurityContextHolder.getUserId());
    }
    //查询选中的购物项
    @Override
    public List<CartInfo> getCartInfos(Long userId) {
        BoundHashOperations<String,String,CartInfo> ops = redisTemplate.boundHashOps("spzx:cart:" + userId);
        List<CartInfo> cartInfos = ops.values().stream().filter(cartInfo ->
                cartInfo.getIsChecked() == 1).collect(Collectors.toList());


        return cartInfos;
    }

    @Override
    public void deleteCheckedCartInfos(Long userId) {

        BoundHashOperations<String,String,CartInfo> ops = redisTemplate
                .boundHashOps("spzx:cart:" + userId);

        ops.entries().forEach((skuIdStr , cartInfo)->{
            if(cartInfo.getIsChecked().intValue()==1){
                ops.delete(skuIdStr);//删除选中的购物项
            }
        });


    }
}
